/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	File:		GlbFile.cpp			*/
/********************************************************/

#include "GlbFile.h"

namespace GlbCls
{

CGlbFile::CGlbFile()
{
	m_ulSize = 0;
	m_pFile = NULL;
	m_iFile = GLB_FAILURE;
}

CGlbFile::~CGlbFile()
{
}

ULONG CGlbFile::GlbFileGetSize()
{
	return m_ulSize;
}

void* CGlbFile::GlbFileGetFile()
{
	return m_pFile;
}

void CGlbFile::GlbFileClose()
{
	if (m_iFile > 0) {
		close(m_iFile);
		m_iFile = GLB_FAILURE;
	}

	return;
}

int CGlbFile::GlbFileMunmap(ULONG ulSize)
{
	ULONG ulLength = 0;
	int iReturn = GLB_SUCCESS;

	if (m_iFile > 0) {
		if (ulSize > 0) {
			ulLength = ulSize;
		}
		else {
			ulLength = m_ulSize;
		}
		munmap(m_pFile, ulLength);
	}
	else {
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

int CGlbFile::GlbFileMmap(int iProt, int iFlag, ULONG ulSize)
{
	ULONG ulLength = 0;
	int iReturn = GLB_SUCCESS;

	if (m_iFile > 0) {
		if (ulSize > 0) {
			ulLength = ulSize;
		}
		else {
			ulLength = m_ulSize;
		}
		m_pFile = mmap(NULL, ulLength, iProt, iFlag, m_iFile, 0);
		if (MAP_FAILED == m_pFile) {
			GLB_ERROR("%s\n", strerror(errno));
			iReturn = GLB_FAILURE;
		}
	}
	else {
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

int CGlbFile::GlbFileCreate(char* pszFile)
{
	int iReturn = GLB_SUCCESS;

	if ((m_iFile = open(pszFile, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) > 0) {
		close(m_iFile);
	}
	else {
		GLB_ERROR("%s\n", strerror(errno));
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

int CGlbFile::GlbFileDelete(char* pszFile)
{
	return unlink(pszFile);
}

int CGlbFile::GlbFileOpen(char* pszFile, int iFlag)
{
	struct stat stFile;
	int iReturn = GLB_SUCCESS;

	if ((m_iFile = open(pszFile, iFlag, S_IRUSR | S_IWUSR)) > 0) {
		fstat(m_iFile, &stFile);
		m_ulSize = stFile.st_size;
	}
	else {
		GLB_ERROR("%s\n", strerror(errno));
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

ULONG CGlbFile::GlbFileLseek(short sWhence, ULONG ulOffset)
{
	ULONG ulReturn = 0;

	if (m_iFile > 0) {
		ulReturn = lseek(m_iFile, ulOffset, sWhence);
	}

	return ulReturn;
}

int CGlbFile::GlbFileFcntl(short sType, short sWhence, ULONG ulStart, ULONG ulLength, int iGlbd)
{
	struct flock stLock;

	memset(&stLock, '\0', sizeof(stLock));
	stLock.l_type = sType;
	stLock.l_len = ulLength;
	stLock.l_start = ulStart;
	stLock.l_whence = sWhence;
	if (GLB_FAILURE == fcntl(m_iFile, iGlbd, &stLock)) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int CGlbFile::GlbFileRead(UCHAR* puszLine, UINT uiLength, bool bProc)
{
	int iReturn = 0;
	ULONG ulOffset = 0;

	if (m_iFile > 0) {
		if (true == bProc) {
			ulOffset = GlbFileLseek(GLB_S_CUR, 0);
			if (GLB_SUCCESS == GlbFileFcntl(GLB_F_RDLCK, GLB_S_SET, ulOffset, uiLength, GLB_F_SETLKW)) {
				iReturn = read(m_iFile, puszLine, uiLength);
				GlbFileFcntl(GLB_F_UNLCK, GLB_S_SET, ulOffset, uiLength, GLB_F_SETLK);
			}
		}
		else {
			iReturn = read(m_iFile, puszLine, uiLength);
		}
	}

	return iReturn;
}

int CGlbFile::GlbFileWrite(UCHAR* puszLine, UINT uiLength, bool bProc)
{
	int iReturn = 0;
	ULONG ulOffset = 0;

	if (m_iFile > 0) {
		if (true == bProc) {
			ulOffset = GlbFileLseek(GLB_S_CUR, 0);
			if (GLB_SUCCESS == GlbFileFcntl(GLB_F_WRLCK, GLB_S_SET, ulOffset, uiLength, GLB_F_SETLKW)) {
				iReturn = write(m_iFile, puszLine, uiLength);
				GlbFileFcntl(GLB_F_UNLCK, GLB_S_SET, ulOffset, uiLength, GLB_F_SETLK);
			}
		}
		else {
			iReturn = write(m_iFile, puszLine, uiLength);
		}
	}

	return iReturn;
}

void CGlbFile::GlbFileMmapGet(ULONG ulOffset, UCHAR* puszLine, UINT uiLength, bool bProc)
{
	UCHAR* puszCur = (UCHAR*)m_pFile;

	if (NULL != puszCur) {
		puszCur += ulOffset;
		if (true == bProc) {
			if (GLB_SUCCESS == GlbFileFcntl(GLB_F_RDLCK, GLB_S_CUR, ulOffset, uiLength, GLB_F_SETLKW)) {
				memcpy(puszLine, puszCur, uiLength);
				GlbFileFcntl(GLB_F_UNLCK, GLB_S_CUR, ulOffset, uiLength, GLB_F_SETLK);
			}
		}
		else {
			memcpy(puszLine, puszCur, uiLength);
		}
	}

	return;
}

void CGlbFile::GlbFileMmapPut(ULONG ulOffset, UCHAR* puszLine, UINT uiLength, bool bProc)
{
	UCHAR* puszCur = (UCHAR*)m_pFile;

	if (NULL != puszCur) {
		puszCur += ulOffset;
		if (true == bProc) {
			if (GLB_SUCCESS == GlbFileFcntl(GLB_F_WRLCK, GLB_S_CUR, ulOffset, uiLength, GLB_F_SETLKW)) {
				memcpy(puszCur, puszLine, uiLength);
				GlbFileFcntl(GLB_F_UNLCK, GLB_S_CUR, ulOffset, uiLength, GLB_F_SETLK);
			}
		}
		else {
			memcpy(puszCur, puszLine, uiLength);
		}
	}

	return;
}

int CGlbFile::GlbFileTruncate(char* pszFile, ULONG ulSize)
{
	if (GLB_SUCCESS != truncate(pszFile, ulSize)) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

} /* GlbCls */
